/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#include "ImageFileReader.hpp"

CImageFileReader::CImageFileReader()
 :iFileReaded(false), 
  iData(),
  iImageInfos(),
  iTimes(),
  iBegin(),
  iEnd(),
  iMaCIGroup(""),
  iInstanceName(""),
  iDirectory(),
  iImageFormat(),
  iImageCount(0)
{
  
}
//*****************************************************************************

CImageFileReader::~CImageFileReader()
{

 iData.clear();
 iTimes.clear();
}
//*****************************************************************************

bool CImageFileReader::ReadFile(std::string aFileName)
{
 dPrint(3,"Opening file '%s'",aFileName.c_str());
  FILE *file= fopen(aFileName.c_str(),"rt");

  char c[200];
  std::string interfaceName;
  char macigroup[256];
  char instanceName[64];
  //  char d[200];

   memset(iDirectory,'\0',512);

  //Directory name for image files are the same than the log file without '.txt'
   aFileName.copy(iDirectory,aFileName.size()-4);

  //Read the seven first lines..and get the interfacename...
  fgets (c, 200,file );
  
  fscanf(file,"%s %s %s %s",c,macigroup,c,instanceName);


  fgets (c, 200,file );
  fgets (c, 200,file );

  std::string s2(c);
  std::string::size_type end;
  std::string::size_type begin = std::string::npos;
  begin = s2.find("image_format:");
  end = s2.find("image_count:");

  if(begin == std::string::npos && end == std::string::npos){
   
    //Just to support old logFiles..
    iImageFormat = MaCI::Image::KImageDataJPEG;
    iImageCount = 1;
  }else if(begin == std::string::npos && end != std::string::npos){
    iImageFormat = MaCI::Image::KImageDataUnknown;
    std::string imagecount = s2.substr(end+13);
    iImageCount = atoi(imagecount.c_str());
  }else{
    
    std::string imageformat= s2.substr(begin+14,end-(begin+14));
    iImageFormat = (MaCI::Image::EImageDataType)atoi(imageformat.c_str());
    std::string imagecount = s2.substr(end+13);
    iImageCount = atoi(imagecount.c_str());
  }
 

  // dPrint(1,"Got %d for imageFormat and %d for imageCount, directory: %s",iImageFormat,iImageCount,iDirectory);
  fgets (c, 200,file );
  //dPrint(1,"c = %s",c);
  fgets (c, 200,file );
  //dPrint(1,"c = %s",c);
  fgets (c, 200,file );  
  //dPrint(1,"c = %s",c);

  

  iMaCIGroup = std::string(macigroup);
  iInstanceName = std::string(instanceName);
  dPrint(1,"Got for macigroup: '%s' and instance name: '%s'",
         iMaCIGroup.c_str(),
         iInstanceName.c_str());


  bool result = ReadData(file);
  iFileReaded = result;
  fclose(file);
  return result;
}
//*****************************************************************************

bool CImageFileReader::GetServiceInformation(std::string &aMaCIGroup,
                                             std::string &aInstanceName)
{
  if(iFileReaded){
    aMaCIGroup = iMaCIGroup;
    aInstanceName = iInstanceName;
  }else{
    dPrint(1,"file not readed, could not give service information");
  }

  return iFileReaded;

}
//*****************************************************************************

bool CImageFileReader::GetTimes(std::list<gim::time> &aTimes)
{
 if(iFileReaded){
    aTimes.assign(iTimes.begin(),iTimes.end());
    return true;
  }else{
    dPrint(1,"File not read, could not give times");
    return false;
  }
}
//*****************************************************************************

bool CImageFileReader::GetTimeLimits(gim::time &aBegin,gim::time &aEnd)
{
  if(iFileReaded){
    aBegin = iBegin;
    aEnd = iEnd;
    return true;
  }else{
     dPrint(1,"File not read, could not give time limits");
    return false;
  }
}
//*****************************************************************************
unsigned int CImageFileReader::GetImageCountPerPacket(void)
{
  if(iFileReaded){
    return iImageCount;
  }else{
     dPrint(1,"File not read, could not give image format");
     return 0;
  }

}
//*****************************************************************************

bool CImageFileReader::GetImageData(MaCI::Image::CImageData &aData,
                                    gim::time aTime)
{
  using namespace MaCI::Image;
  MaCI::Image::CImageData data;
  CImageContainer idc;
  static char buffer[4096 * 1000];
  MaCI::Common::TTimestamp timestamp(aTime);
  int b;
  int r;

  /**/
  char wholeFileName[512];
  // Create backend.
  data.Reset();
  r = data.CreateInternalBinBag();
  /**/
  
  
  
  std::map<gim::time,std::vector<unsigned int> >::iterator iter
    =iData.find(aTime);

  std::map<gim::time,std::vector<MaCI::Image::TImageInfo> >::iterator imageInfoIter
    =iImageInfos.find(aTime);
  if(iter != iData.end() && imageInfoIter != iImageInfos.end()){
    //Construct image
    data.SetTimestamp(timestamp); // Set timestamp
  
  


    for(unsigned int i = 0; i< iImageCount; i++){
     
      if(imageInfoIter->second[i].imagedatatype == MaCI::Image::KImageDataJPEG){
      

        if(i == 0){
          //        dPrint(1,"0");
          sprintf(wholeFileName,"%s/%.6d_%.6d.jpg",
                  iDirectory,timestamp.timestamp_s,timestamp.timestamp_us);
        }else{
          //dPrint(1,"%d",i);
          sprintf(wholeFileName,"%s/%d/%.6d_%.6d.jpg",
                  iDirectory, i,timestamp.timestamp_s,timestamp.timestamp_us);
        }
        
        
        //Open file and save it to buffer
        
        FILE *imageFile = fopen(wholeFileName, "rb");
        dPrint(1,"Trying to open file '%s'",wholeFileName);
        assert(imageFile != NULL);
        b = fread(buffer,iter->second[i],1,imageFile);
        fclose(imageFile);
        assert(b==1);
        
        
        // Only using Decoder for determining the image size.
        CJPEGDecoder d(buffer, iter->second[i]);
        const int w = d.GetImageWidth();
        const int h = d.GetImageHeight();
        
        dPrint(1,"Image found. Image is '%d x %d'.", w, h);
        // Add to container.
        idc.SetImageData((const unsigned char *)buffer, 
                         iter->second[i], 
                         KImageDataJPEG,
                         w, h, 
                         KImageDataUnknown,
                         true); // COPY!
      }else if(imageInfoIter->second[i].imagedatatype == MaCI::Image::KImageDataPNG){

        if(i == 0){
          //        dPrint(1,"0");
          sprintf(wholeFileName,"%s/%.6d_%.6d.png",
                  iDirectory,timestamp.timestamp_s,timestamp.timestamp_us);
        }else{
          //dPrint(1,"%d",i);
          sprintf(wholeFileName,"%s/%d/%.6d_%.6d.png",
                  iDirectory, i,timestamp.timestamp_s,timestamp.timestamp_us);
        }
        //Open file and save it to buffer
        
        FILE *imageFile = fopen(wholeFileName, "rb");
        dPrint(1,"Trying to open file '%s'",wholeFileName);
        assert(imageFile != NULL);
        b = fread(buffer,iter->second[i],1,imageFile);
        fclose(imageFile);
        assert(b==1);
        // Only using Decoder for determining the image size.
        const int w = imageInfoIter->second[i].imagewidth;
        const int h = imageInfoIter->second[i].imageheight;
        dPrint(1,"Image found. Image is '%d x %d'.", w, h);
        // Add to container.
        idc.SetImageData((const unsigned char *)buffer, 
                         iter->second[i], 
                         KImageDataPNG,
                         w, h, 
                         KImageDataUnknown,
                         true); // COPY!
      }else{

        dPrint(1,"ERROR. DON'T KNOW HOW TO HANDLE THIS TYPE OF IMAGES (type %u)",
               imageInfoIter->second[i].imagedatatype);
        return false;
      }
      

      
      dPrint(1,"Adding image");
      r &= data.AddImage(0, idc);
      assert(r == true);
     

        
    

    }
    
    aData = data;
    
    return true;
  }else{
    
    return false;
  }
}
//*****************************************************************************

bool CImageFileReader::ReadData(FILE * iFile)
{

  using namespace MaCI::Image;
  MaCI::Common::TTimestamp timestamp;
  unsigned int fileSize;
  int number = 1;
  bool first = true;
  unsigned int format;
  unsigned int width,height;
  while(number != 0 && number != EOF){
    std::vector<unsigned int> dataSizeList;
    std::vector<MaCI::Image::TImageInfo> infos;
    number = fscanf(iFile,"%u %u ",
                    &(timestamp.timestamp_s),
                    &(timestamp.timestamp_us));
    if(number != EOF){
      for(unsigned int i = 0; i< iImageCount; i++){
        if(iImageFormat ==  MaCI::Image::KImageDataJPEG){
          number += fscanf(iFile,"%u",
                           &fileSize);
          
          dataSizeList.push_back(fileSize);
          infos.push_back(MaCI::Image::TImageInfo(0,0 ,MaCI::Image::KImageDataJPEG,0));
        }else{
          number += fscanf(iFile,"%u %u %u %u",
                           &fileSize,
                           &format,
                           &width,
                           &height);
          dataSizeList.push_back(fileSize);
          infos.push_back(MaCI::Image::TImageInfo(width,height ,(MaCI::Image::EImageDataType)(format),0));
          
        }
        if(first && number >= 3){
          
          iBegin = timestamp.GetGimTime();
          
          first = false;
        }    
      }
    }
    if(number> 0){
      
      //Open the file 
      
      iData[timestamp.GetGimTime()] = dataSizeList;
      iImageInfos[timestamp.GetGimTime()] = infos;

      iTimes.push_back(timestamp.GetGimTime());
    }
    
  
    ownSleep_ms(1);

  }
  if(!first){
    iEnd = timestamp.GetGimTime();
    dPrint(1,"Got first time %d %d, last %d %d",iBegin.seconds,iBegin.useconds,iEnd.seconds,iEnd.useconds);
  }
  if(number == EOF){
    return true;
  }else{
    return false;
  }

}
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
  
  
  
